//import type { AxiosRequestConfig, Method } from 'axios'
import type { AxiosRequestConfig, AxiosResponse, AxiosError, Method } from 'axios'
import axios from 'axios'
import { ElLoading, ElNotification, type LoadingOptions } from 'element-plus'
import { useUserInfo } from '../stores/userInfo'
//import { useConfig } from '../stores/config'



interface anyObj {
  [key: string]: any
}


interface ApiResponse<T = any> {
  code: number
  data: T
  msg: string
  time: number
}

type ApiPromise<T = any> = Promise<ApiResponse<T>>


const requests = []
let tokenRefreshing = false
const pendingMap = new Map()
const loadingInstance: LoadingInstance = {
    target: null,
    count: 0,
}



/**
 * 根据运行环境获取基础请求URL
 */
export const getUrl = (): string => {
    //const value: string = import.meta.env.VITE_AXIOS_BASE_URL as string
    //const url = value == 'getCurrentDomain' ? window.location.protocol + '//' + window.location.host : value
    //console.log(value)  // http://localhost:8000
    //console.log(window.location.protocol) // http:
    //console.log(window.location.host)  // localhost:1818
    //console.log(url)  // http://localhost:8000
    //const url = 'http://www.enshop.com/'
    const url = 'https://rascalapi.nbwpress.com/'
    return url
}

/**
 * 根据运行环境获取基础请求URL的端口
 */
export const getUrlPort = (): string => {
    const url = getUrl()
    return new URL(url).port
}

/**
 * 创建`Axios`
 * 默认开启`reductDataFormat(简洁响应)`,返回类型为`ApiPromise`
 * 关闭`reductDataFormat`,返回类型则为`AxiosPromise`
 */
function createAxios<Data = any, T = ApiPromise<Data>>(axiosConfig: AxiosRequestConfig, options: Options = {}, loading: LoadingOptions = {}): T {
    //const config = useConfig()
    const userInfo = useUserInfo()


    const Axios = axios.create({
        baseURL: getUrl(),
        timeout: 1000 * 10,
        headers: {
            'build-admin': true,
            //"withCredentials": true
            //server: true,
        },
        responseType: 'json',
    })


    //console.log(axiosConfig.url)

    // 合并默认请求选项
    options = Object.assign(
        {
            CancelDuplicateRequest: true, // 是否开启取消重复请求, 默认为 true
            loading: false, // 是否开启loading层效果, 默认为false
            reductDataFormat: true, // 是否开启简洁的数据结构响应, 默认为true
            showErrorMessage: true, // 是否开启接口错误信息展示,默认为true
            showCodeMessage: true, // 是否开启code不为1时的信息提示, 默认为true
            showSuccessMessage: false, // 是否开启code为1时的信息提示, 默认为false
            anotherToken: '', // 当前请求使用另外的用户token
        },
        options
    )

    // 请求拦截
    Axios.interceptors.request.use(
        (config) => {
          console.log('请求拦截：配置', config)
            // eslint-disable-next-line @typescript-eslint/no-unused-expressions
            options.CancelDuplicateRequest && addPending(config)
            // 创建loading实例
            if (options.loading) {
                loadingInstance.count++
                if (loadingInstance.count === 1) {
                    loadingInstance.target = ElLoading.service(loading)
                }
            }

            // 自动携带token
            //console.log(config.headers)
            if (config.headers) {
                const userToken = options.anotherToken || userInfo.getToken()
                if (userToken) (config.headers as anyObj)['user-token'] = userToken
            }

            return config
        },
        (error) => {
            return Promise.reject(error)
        }
    )

    // 响应拦截
    Axios.interceptors.response.use(
      (response: AxiosResponse) => {
          console.log('响应拦截返回============', options.reductDataFormat, response.data)

            removePending(response.config)
            //options.loading && closeLoading(options) // 关闭loading
            if(options.loading){
              closeLoading(options)
            }

            if (response.config.responseType == 'json') {
                // 请求失败
                if (response.data && response.data.code !== 200) {
                    if (response.data.code == 409) {
                        if (!tokenRefreshing) {
                            tokenRefreshing = true
                        } else {
                            return new Promise((resolve) => {
                                // 用函数形式将 resolve 存入，等待刷新后再执行
                                requests.push((token: string, type: string) => {
                                    if (type == 'admin-refresh') {
                                        response.headers['back-token'] = `${token}`
                                    } else {
                                        response.headers['user-token'] = `${token}`
                                    }
                                    resolve(Axios(response.config))
                                })
                            })
                        }
                    }
                    if (options.showCodeMessage) {
                        ElNotification({
                            type: 'error',
                            message: response.data.msg,
                            zIndex: 9999,
                        })
                    }
                    // 自动跳转到路由name或path
                    if (response.data.code == 302) {
                        //router.push({ path: response.data.data.routePath ?? '', name: response.data.data.routeName ?? '' })
                    }
                    if (response.data.code == 100) {
                        //let routerPath = '/login'
                        window.location.href = '/Signin';

                        //console.log(response.data)
                        // 需要登录，清理 token，转到登录页
                        // userInfo.removeToken()

                        //router.push({ path: routerPath })
                    }
                    // code不等于200, 页面then内的具体逻辑就不执行了
                    return Promise.reject(response.data)
                } else if (options.showSuccessMessage && response.data && response.data.code == 200) {
                    ElNotification({
                        message: response.data.msg ? response.data.msg : 'axios.Operation successful',
                        type: 'success',
                        zIndex: 9999,
                    })
                }
            }

            return options.reductDataFormat ? response.data : response
        },
        (error: AxiosError) => {
          console.log(error)

          //error.config && removePending(error.config)
          if(error.config){
            removePending(error.config)
          }


            //options.loading && closeLoading(options) // 关闭loading
            if(options.loading){
              closeLoading(options) // 关闭loading
            }


            //options.showErrorMessage && httpErrorStatusHandle(error) // 处理错误状态码
            if(options.showErrorMessage){
              httpErrorStatusHandle(error) // 处理错误状态码
            }

            return Promise.reject(error) // 错误继续返回给到具体页面
        }
    )
    return Axios(axiosConfig) as T
}

export default createAxios

/**
 * 处理异常
 * @param {*} error
 */
function httpErrorStatusHandle(error: any) {
    // 处理被取消的请求
    if (axios.isCancel(error)) return console.error('Automatic cancellation due to duplicate request:' + error.message)
    let message = ''
    if (error && error.response) {
        switch (error.response.status) {
            case 302:
                message = 'axios.Interface redirected!'
                break
            case 400:
                message = 'axios.Incorrect parameter!'
                break
            case 401:
                message = 'axios.You do not have permission to operate!'
                break
            case 403:
                message = 'axios.You do not have permission to operate!'
                break
            case 404:
                message = 'axios.Error requesting address:' + error.response.config.url
                break
            case 408:
                message = 'axios.Request timed out!'
                break
            case 409:
                message = 'axios.The same data already exists in the system!'
                break
            case 500:
                message = 'axios.Server internal error!'
                break
            case 501:
                message = 'axios.Service not implemented!'
                break
            case 502:
                message = 'axios.Gateway error!'
                break
            case 503:
                message = 'axios.Service unavailable!'
                break
            case 504:
                message = 'axios.The service is temporarily unavailable Please try again later!'
                break
            case 505:
                message = 'axios.HTTP version is not supported!'
                break
            default:
                message = 'axios.Abnormal problem, please contact the website administrator!'
                break
        }
    }
    if (error.message.includes('timeout')) message = 'axios.Network request timeout!'
    if (error.message.includes('Network'))
        message = window.navigator.onLine ? 'axios.Server exception!' : 'axios.You are disconnected!'

    ElNotification({
        type: 'error',
        message,
        zIndex: 9999,
    })
}

/**
 * 关闭Loading层实例
 */
function closeLoading(options: Options):void  {
    if (options.loading && loadingInstance.count > 0){
      loadingInstance.count--
    }

    if (loadingInstance.count === 0) {
        loadingInstance.target.close()
        loadingInstance.target = null
    }
}

/**
 * 储存每个请求的唯一cancel回调, 以此为标识
 */
function addPending(config: AxiosRequestConfig) {
    const pendingKey = getPendingKey(config)
    config.cancelToken =
        config.cancelToken ||
        new axios.CancelToken((cancel) => {
            if (!pendingMap.has(pendingKey)) {
                pendingMap.set(pendingKey, cancel)
            }
        })
}

/**
 * 删除重复的请求
 */
function removePending(config: AxiosRequestConfig) {
    const pendingKey = getPendingKey(config)
    if (pendingMap.has(pendingKey)) {
        const cancelToken = pendingMap.get(pendingKey)
        cancelToken(pendingKey)
        pendingMap.delete(pendingKey)
    }
}

/**
 * 生成每个请求的唯一key
 */
function getPendingKey(config: AxiosRequestConfig) {
    let { data } = config
    const { url, method, params, headers } = config
    if (typeof data === 'string') data = JSON.parse(data) // response里面返回的config.data是个字符串对象
    return [
        url,
        method,
        headers && (headers as anyObj)['back-token'] ? (headers as anyObj)['back-token'] : '',
        headers && (headers as anyObj)['user-token'] ? (headers as anyObj)['user-token'] : '',
        JSON.stringify(params),
        JSON.stringify(data),
    ].join('&')
}

/**
 * 根据请求方法组装请求数据/参数
 */
export function requestPayload(method: Method, data: anyObj) {
    if (method == 'GET') {
        return {
            params: data,
        }
    } else if (method == 'POST') {
        return {
            data: data,
        }
    }
}

interface LoadingInstance {
    target: any
    count: number
}
interface Options {
    // 是否开启取消重复请求, 默认为 true
    CancelDuplicateRequest?: boolean
    // 是否开启loading层效果, 默认为false
    loading?: boolean
    // 是否开启简洁的数据结构响应, 默认为true
    reductDataFormat?: boolean
    // 是否开启接口错误信息展示,默认为true
    showErrorMessage?: boolean
    // 是否开启code不为1时的信息提示, 默认为true
    showCodeMessage?: boolean
    // 是否开启code为1时的信息提示, 默认为false
    showSuccessMessage?: boolean
    // 当前请求使用另外的用户token
    anotherToken?: string
}

/*
 * 感谢掘金@橙某人提供的思路和分享
 * 本axios封装详细解释请参考：https://juejin.cn/post/6968630178163458084?share_token=7831c9e0-bea0-469e-8028-b587e13681a8#heading-27
 */
